home *** CD-ROM | disk | FTP | other *** search
- From: Torsten Scherer <itschere@techfak.uni-bielefeld.de>
- Subject: MiNT 1.09 security: revised f_delete() patch + more
- Date: Sat, 18 Dec 93 15:40:56 +0100
- benni@phil15.uni-sb.de
- In-Reply-To: <9312171520.AA24380@suntopo.matups.fr>; from "Thierry Bousch" at Dec 17, 93 4:19 pm
-
- Bonjour Thierry!
-
- > Hmm, if you want to support the sticky bit, you must also patch the
- > f_rename() and f_rmdir() functions, because you shouldn't be allowed to
- > rename/move files and subdirectories of a sticky folder. (Otherwise, it
- > would be a big security hole: you could move files to a non-sticky
- > folder, and delete them.)
-
- So it wasn't directly wrong, but just incomplete. Thanx for this info,
- you're of course right! This should be fixed with this revised patch,
- which is again relative to the original code because:
-
- 1) everyone should have made a backup before
- 2) everyone should know how to unpatch a previous patch
- 3) probably nobody has applied the old one anyway ;-)
-
- Now f_delete(), f_rename() and d_delete() are patched so that you may
- not do an operation you want if "the sticky bit is set, and you're not
- superuser, and the item doesn't belong to you, and - in addition to your
- ramfs - the directory doesn't belong to you."
-
- You could in any case change the filemode of the directory if it belongs
- to you and then do what you like, but it seems more logical and/or convenient
- to me to do it this way.
-
- I've also changed the d_setpath() call so that it is now no longer allowed
- to change to a directory you don't have permission to. Until now, you can
- _change_ to any directory you like, but maybe refused to read it later. So
- this isn't a big problem, but it looks to be a bit more un*x like. :-)
-
- Je yous souhaites un bon joel, un tres bien annee' nouvaux et peut-`etre
- aussi des bon vacances d'hiver, si vous aller faire du ski ou quelque
- chose comme ,ca.
-
- Oh no, my french... :-(
-
- anyway, happy X-Mas and a jolly new year 4 all :-)
- TeSche
- --
- PS: If the above written looks weird, then that's probably because it _is_.
- WhoDunnIt: Torsten Scherer (Schiller, Tesche, ...)
- Where: Faculty of Technology, University of Bielefeld, Germany
- EMail: itschere@techfak.uni-bielefeld.de / tesche@hrz.uni-bielefeld.de
-
- ======= cut cut cut =======
- diff -u5 ./dosdir.c ../my/dosdir.c
- --- ./dosdir.c Fri Nov 19 15:34:12 1993
- +++ ../my/dosdir.c Sun Dec 19 14:19:58 1993
- @@ -113,11 +113,11 @@
- if (r) {
- DEBUG(("Dcreate(%s): returning %ld", path, r));
- return r; /* an error occured */
- }
- /* check for write permission on the directory */
- - r = dir_access(&dir, S_IWOTH);
- + r = dir_access(&dir, S_IWOTH, 0);
- if (r) {
- DEBUG(("Dcreate(%s): access to directory denied",path));
- release_cookie(&dir);
- return r;
- }
- @@ -124,10 +124,13 @@
- r = (*dir.fs->mkdir)(&dir, temp1, DEFAULT_DIRMODE & ~curproc->umask);
- release_cookie(&dir);
- return r;
- }
-
- +/* tesche: delete a directory with respect of the sticky bit
- + */
- +
- long ARGS_ON_STACK
- d_delete(path)
- const char *path;
- {
- fcookie parentdir, targdir;
- @@ -134,10 +137,11 @@
- long r;
- PROC *p;
- int i;
- XATTR xattr;
- char temp1[PATH_MAX];
- + short sticky_uid;
-
- TRACE(("Ddelete(%s)", path));
-
- r = path2cookie(path, temp1, &parentdir);
-
- @@ -147,18 +151,17 @@
- return r;
- }
- /* check for write permission on the directory which the target
- * is located
- */
- - if ((r = dir_access(&parentdir, S_IWOTH)) != 0) {
- + if ((r = dir_access(&parentdir, S_IWOTH, &sticky_uid))) {
- DEBUG(("Ddelete(%s): access to directory denied", path));
- release_cookie(&parentdir);
- return r;
- }
-
- /* now get the info on the file itself */
- -
- r = relpath2cookie(&parentdir, temp1, NULL, &targdir, 0);
- if (r) {
- bailout:
- release_cookie(&parentdir);
- DEBUG(("Ddelete: error %ld on %s", r, path));
- @@ -167,10 +170,20 @@
- if ((r = (*targdir.fs->getxattr)(&targdir, &xattr)) != 0) {
- release_cookie(&targdir);
- goto bailout;
- }
-
- +/* check for sticky bit */
- + if ((sticky_uid >= 0) &&
- + curproc->euid &&
- + (sticky_uid != curproc->euid) &&
- + (curproc->euid != xattr.uid)) {
- + release_cookie(&targdir);
- + release_cookie(&parentdir);
- + return EACCDN;
- + }
- +
- /* if the "directory" is a symbolic link, really unlink it */
- if ( (xattr.mode & S_IFMT) == S_IFLNK ) {
- r = (*parentdir.fs->remove)(&parentdir, temp1);
- } else if ( (xattr.mode & S_IFMT) != S_IFDIR ) {
- DEBUG(("Ddelete: %s is not a directory", path));
- @@ -215,11 +228,10 @@
- fcookie dir;
- int drv = curproc->curdrv;
- int i;
- char c;
- long r;
- - XATTR xattr;
-
- TRACE(("Dsetpath(%s)", path));
-
- r = path2cookie(path, follow_links, &dir);
-
- @@ -234,24 +246,16 @@
- drv = c-'a';
- else if (c >= 'A' && c <= 'Z')
- drv = c-'A';
- }
-
- - r = (*dir.fs->getxattr)(&dir, &xattr);
- -
- - if (r < 0) {
- - DEBUG(("Dsetpath: file '%s': attributes not found", path));
- + if ((r = dir_access(&dir, S_IXOTH, 0))) {
- + DEBUG(("Dsetpath(%s): not a directory or access denied", path));
- release_cookie(&dir);
- return r;
- }
-
- - if (!(xattr.attr & FA_DIR)) {
- - DEBUG(("Dsetpath(%s): not a directory",path));
- - release_cookie(&dir);
- - return EPTHNF;
- - }
- -
- /*
- * watch out for symbolic links; if c:\foo is a link to d:\bar, then
- * "cd c:\foo" should also change the drive to d:
- */
- if (drv != UNIDRV && dir.dev != curproc->root[drv].dev) {
- @@ -504,11 +508,11 @@
- }
-
- /* check to see if we have read permission on the directory (and make
- * sure that it really is a directory!)
- */
- - r = dir_access(&dir, S_IROTH);
- + r = dir_access(&dir, S_IROTH, 0);
- if (r) {
- DEBUG(("Fsfirst(%s): access to directory denied (error code %ld)", path, r));
- release_cookie(&dir);
- return r;
- }
- @@ -716,48 +720,88 @@
- release_cookie(&fc);
- return xattr.attr;
- }
- }
-
- +/* tesche: delete a file with respect of the sticky bit
- + */
- +
- long ARGS_ON_STACK
- f_delete(name)
- const char *name;
- {
- - fcookie dir;
- - long r;
- - char temp1[PATH_MAX];
- + fcookie dir, fc;
- + long r;
- + char temp1[PATH_MAX];
- + XATTR fxattr;
- + short sticky_uid;
-
- TRACE(("Fdelete(%s)", name));
-
- - r = path2cookie(name, temp1, &dir);
- -
- - if (r) {
- - DEBUG(("Fdelete: error %ld", r));
- +/* first, get the directory cookie */
- + if ((r = path2cookie(name, temp1, &dir))) {
- + DEBUG(("Fdelete(%s): directory not found", name));
- return r;
- }
-
- /* check for write permission on directory */
- - r = dir_access(&dir, S_IWOTH);
- - if (r) {
- - DEBUG(("Fdelete(%s): write access to directory denied",name));
- - } else {
- -/* BUG: we should check here for a read-only file */
- - r = (*dir.fs->remove)(&dir,temp1);
- + if (dir_access(&dir, S_IWOTH, &sticky_uid)) {
- + DEBUG(("Fdelete(%s): write access to directory denied", name));
- + release_cookie(&dir);
- + return EACCDN;
- }
- +
- +/* if (sticky) and not(superuser) and not(my_directory): need more checks */
- + if ((sticky_uid >= 0) &&
- + curproc->euid &&
- + (sticky_uid != curproc->euid)) {
- + if ((r = relpath2cookie(&dir, temp1, 0, &fc, 0))) {
- + DEBUG(("Fdelete(%s): error %ld, perhaps file not found", name, r));
- + release_cookie(&dir);
- + return r;
- + }
- +
- + /* check ownership of the file */
- + if ((r = (fc.fs->getxattr)(&fc, &fxattr))) {
- + DEBUG(("Fdelete(%s): can't get file attributes", name));
- + release_cookie(&fc);
- + release_cookie(&dir);
- + return r;
- + }
- +
- + if (curproc->euid != fxattr.uid) {
- + DEBUG(("Fdelete(%s): write access to file denied", name));
- + release_cookie(&fc);
- + release_cookie(&dir);
- + return EACCDN;
- + }
- +
- + release_cookie(&fc);
- + } /* sticky */
- +
- +/* actually delete the file */
- + if ((r = (*dir.fs->remove)(&dir,temp1)))
- + DEBUG(("Fdelete(%s): error %ld", name, r));
- +
- release_cookie(&dir);
- +
- return r;
- }
-
- +/* tesche: rename/move a file with respect of the sticky bit
- + */
- +
- long ARGS_ON_STACK
- f_rename(junk, old, new)
- int junk; /* ignored, for TOS compatibility */
- const char *old, *new;
- {
- fcookie olddir, newdir, oldfil;
- XATTR xattr;
- char temp1[PATH_MAX], temp2[PATH_MAX];
- long r;
- + short sticky_uid;
-
- UNUSED(junk);
-
- TRACE(("Frename(%s, %s)", old, new));
-
- @@ -799,12 +843,21 @@
- release_cookie(&newdir);
- return EXDEV; /* cross device rename */
- }
-
- /* check for write permission on both directories */
- - r = dir_access(&olddir, S_IWOTH);
- - if (!r) r = dir_access(&newdir, S_IWOTH);
- + if (!(r = dir_access(&olddir, S_IWOTH, &sticky_uid)))
- + r = dir_access(&newdir, S_IWOTH, 0);
- +
- +/* check for sticky bit */
- + if (!r &&
- + (sticky_uid >= 0) &&
- + curproc->euid &&
- + (sticky_uid != curproc->euid) &&
- + (xattr.uid != curproc->euid)) /* oldfil specs */
- + r = EACCDN;
- +
- if (r) {
- DEBUG(("Frename(%s,%s): access to a directory denied",old,new));
- } else {
- r = (*newdir.fs->rename)(&olddir, temp2, &newdir, temp1);
- }
- @@ -873,11 +926,11 @@
- r = path2cookie(name, follow_links, &dir);
- if (r) {
- DEBUG(("Dopendir(%s): error %ld", name, r));
- return r;
- }
- - r = dir_access(&dir, S_IROTH);
- + r = dir_access(&dir, S_IROTH, 0);
- if (r) {
- DEBUG(("Dopendir(%s): read permission denied", name));
- release_cookie(&dir);
- return r;
- }
- @@ -1042,11 +1095,11 @@
- return EXDEV; /* cross device link */
- }
-
- /* check for write permission on the destination directory */
-
- - r = dir_access(&newdir, S_IWOTH);
- + r = dir_access(&newdir, S_IWOTH, 0);
- if (r) {
- DEBUG(("Flink(%s,%s): access to directory denied",old,new));
- } else
- r = (*newdir.fs->hardlink)(&olddir, temp2, &newdir, temp1);
- release_cookie(&olddir);
- @@ -1072,11 +1125,11 @@
- r = path2cookie(new, temp1, &newdir);
- if (r) {
- DEBUG(("Fsymlink(%s,%s): error parsing %s", old,new,new));
- return r;
- }
- - r = dir_access(&newdir, S_IWOTH);
- + r = dir_access(&newdir, S_IWOTH, 0);
- if (r) {
- DEBUG(("Fsymlink(%s,%s): access to directory denied",old,new));
- } else
- r = (*newdir.fs->symlink)(&newdir, temp1, old);
- release_cookie(&newdir);
- diff -u5 ./filesys.c ../my/filesys.c
- --- ./filesys.c Fri Nov 19 15:34:22 1993
- +++ ../my/filesys.c Sat Dec 18 14:41:38 1993
- @@ -1100,16 +1100,18 @@
- return t;
- }
-
- /*
- * check to see that a file is a directory, and that write permission
- - * is granted; return an error code, or 0 if everything is ok.
- + * is granted; return an error code, or 0 if everything is ok. also return
- + * the uid of the directory if the sticky bit is set, or -1 otherwise,
- */
- long
- -dir_access(dir, perm)
- +dir_access(dir, perm, sticky_uid)
- fcookie *dir;
- unsigned perm;
- + short *sticky_uid;
- {
- XATTR xattr;
- long r;
-
- r = (*dir->fs->getxattr)(dir, &xattr);
- @@ -1122,10 +1124,16 @@
- return EPTHNF;
- }
- if (denyaccess(&xattr, perm)) {
- DEBUG(("no permission for directory"));
- return EACCDN;
- + }
- + if (sticky_uid) {
- + if (xattr.mode & S_ISVTX) {
- + *sticky_uid = xattr.uid;
- + } else
- + *sticky_uid = -1;
- }
- return 0;
- }
-
- /*
- diff -u5 ./proto.h ../my/proto.h
- --- ./proto.h Fri Nov 19 15:34:38 1993
- +++ ../my/proto.h Sat Dec 18 14:42:16 1993
- @@ -182,11 +182,11 @@
- FILEPTR *new_fileptr P_((void));
- void dispose_fileptr P_((FILEPTR *f));
- int ARGS_ON_STACK denyshare P_((FILEPTR *list, FILEPTR *newfileptr));
- int denyaccess P_((XATTR *, unsigned));
- LOCK * ARGS_ON_STACK denylock P_((LOCK *list, LOCK *newlock));
- -long dir_access P_((fcookie *, unsigned));
- +long dir_access P_((fcookie *, unsigned, short *));
- int has_wild P_((const char *name));
- void copy8_3 P_((char *dest, const char *src));
- int pat_match P_((const char *name, const char *template));
- int samefile P_((fcookie *, fcookie *));
-
-